package com.kgcx.price.service;

import com.kgcx.common.client.coupon.CouponClient;
import com.kgcx.common.client.coupon.pojo.Coupon;
import com.kgcx.common.client.order.OrderClient;
import com.kgcx.common.exception.BusinessException;
import com.kgcx.common.utils.CollectionUtils;
import com.kgcx.common.utils.GaodeApi;
import com.kgcx.price.domain.PriceCaculationPrice;
import com.kgcx.price.domain.TPriceCaculationRule;
import com.kgcx.price.mapper.PriceCaculationPriceMapper;
import com.kgcx.price.mapper.TPriceCaculationRuleMapper;
import com.kgcx.price.utils.DateUtil;
import com.kgcx.price.utils.MqttClientUtil;
import com.kgcx.price.utils.MqttServiceUtil;
import com.kgcx.price.utils.SystemVariable;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * CaculationRule 预估价计算类 Service层
 *
 * @author:zhoumeile
 * @date:2017/11/07
 */
@Service
public class PriceCaculationPriceService {
    @Autowired
    private PriceCaculationPriceMapper priceCaculationPriceMapper;

    @Autowired
    private TPriceCaculationRuleMapper tPriceCaculationRuleMapper;

    @Autowired
    private CouponClient couponClient;

    @Autowired
    private GaodeApi gaodeApi;

    @Autowired
    private OrderClient orderClient;

    @Autowired
    private MqttClientUtil mqttClient;

    @Autowired
    private MqttServiceUtil mqttService;

    /**
     * getPriceCaculationPriceByOrderId 根据订单Id取得预估价信息
     *
     * @param priceCaculationPrice 预估价信息类
     * @return PriceCaculationPrice
     */
    @Transactional(rollbackFor = Exception.class)
    public PriceCaculationPrice caculatePrice(PriceCaculationPrice priceCaculationPrice) {
        TPriceCaculationRule tPriceCaculationRuleForDb = new TPriceCaculationRule();

        if (priceCaculationPrice.getCarType() != null) {
            tPriceCaculationRuleForDb.setCarType(priceCaculationPrice.getCarType());
        } else {
            throw new BusinessException(SystemVariable.ERROR_RETURN_CODE, "用车类型为空！");
        }

        if (priceCaculationPrice.getCityId() != null) {
            tPriceCaculationRuleForDb.setCityId(priceCaculationPrice.getCityId());
        } else {
            throw new BusinessException(SystemVariable.ERROR_RETURN_CODE, "城市为空！");
        }


//        if (customerId == null) {
//            return new ReturnData<>(SystemVariable.ERROR_RETURN_CODE, "乘客为空！");
//        }

        if (priceCaculationPrice.getOrderStartTime() == null) {
            throw new BusinessException(SystemVariable.ERROR_RETURN_CODE, "订单开始时间为空！");
        }

        /** 根据城市、用车类型取得唯一一条报价规则信息 */
        TPriceCaculationRule tPriceCaculationRule = tPriceCaculationRuleMapper.getByCityIdCarType(tPriceCaculationRuleForDb);

        /** 如果查询到报价规则相关信息则进行价格预估，否则抛错 */
        if (tPriceCaculationRule != null) {
            /** 订单预估总价 */
            Long totalPrice;
            /** 起步基础价 */
            BigDecimal startFee = tPriceCaculationRule.getStartFee();
            /** 时长单价 */
            BigDecimal unitpriceperminute = tPriceCaculationRule.getUnitpriceperminute();
            /** 公里单价 */
            BigDecimal unitpricepermile = tPriceCaculationRule.getUnitpricepermile();
            /** 远途费单价 */
            BigDecimal travelFee = tPriceCaculationRule.getFarAwayPrice();
            /** 出城费单价 */
            BigDecimal outCityPerFee = tPriceCaculationRule.getOutTownPrice();
            /** 夜间服务费单价 */
            BigDecimal evePerFee = tPriceCaculationRule.getNightPrice();
            /** 总时长价 */
            BigDecimal minuteFee;
            /** 总公里价 */
            BigDecimal mileFee;
            /** 远途总价 */
            BigDecimal travelTotleFee = new BigDecimal(0);
            /** 出城费总价 */
            BigDecimal outCityFee = new BigDecimal(0);
            /** 夜间服务费总价 */
            BigDecimal eveFee = new BigDecimal(0);
            /** 抹零数 */
            Long zero;
            /** 订单预估价(抹零后) */
            Long totalMoney;
            /** 优惠券价格 */
            Long conponFee = 0L;

            priceCaculationPrice.setPriceId(tPriceCaculationRule.getKid());

            /** 存数据库，都存基本单位 分 */
            startFee = startFee.multiply(new BigDecimal(100));
            priceCaculationPrice.setStartFee(startFee.longValue());

            /** 计价规则类型 1套餐 2普通 3一口价 */
            priceCaculationPrice.setCalType(1);


            /** 根据高德路径规划返回行驶里程、时间预估总里程价、总时间价 */
            Map<String, String> gaodeMap = gaodeApi.getGaodeRestapi(priceCaculationPrice.getOrigin(), priceCaculationPrice.getDestination(), 5);

            if (!gaodeMap.get("msg").equals("OK")) {
                throw new BusinessException(SystemVariable.ERROR_RETURN_CODE, "调用高德失败:" + gaodeMap.get("msg"));
            } else {
                priceCaculationPrice.setMileage(Long.parseLong(gaodeMap.get("distance")));
                priceCaculationPrice.setTime(Integer.parseInt(gaodeMap.get("duration")));

                BigDecimal distance = (new BigDecimal(gaodeMap.get("distance")).divide(new BigDecimal(1000))).setScale(1, BigDecimal.ROUND_DOWN);

                /** 计算总时长费,分钟为单位 总用时 * 每分钟单价 */
                minuteFee = unitpriceperminute.multiply(new BigDecimal(Long.valueOf(gaodeMap.get("duration")) / 60)).multiply(new BigDecimal(100));
                /** 计算公里价 */
                mileFee = distance.multiply(unitpricepermile).multiply(new BigDecimal(100));

                /** 分 */
                priceCaculationPrice.setMileageMoney(mileFee.longValue());
                /** 分 */
                priceCaculationPrice.setTimeFee(minuteFee.longValue());

                /** 计算是否有远途费,单位为米，限制为15公里 */
                if (distance.compareTo(SystemVariable.TRAVEL_MILE) == 1) {
                    priceCaculationPrice.setTravelFlag(1);
                    /** 计算远途费 远途费 - 15公里 * 远途费单价 */
                    travelTotleFee = distance.subtract(SystemVariable.TRAVEL_MILE).multiply(travelFee).multiply(new BigDecimal(100));

                    priceCaculationPrice.setKmLong(distance.subtract(SystemVariable.TRAVEL_MILE).multiply(new BigDecimal(1000)).longValue());
                } else {
                    priceCaculationPrice.setTravelFlag(0);
                }

                priceCaculationPrice.setTravelFee(travelTotleFee.longValue());

                /** 调用高德逆地理编码接口，根据返回cityCode判断是否出城 */
                List<Map<String, String>> gaodeGeocode = gaodeApi.geocode(priceCaculationPrice.getOrigin() + "|" + priceCaculationPrice.getDestination());

                /** 根据高德逆地理编码返回 citycode 判断是否相等 */
                if (gaodeGeocode.get(0).get("citycode").equals(gaodeGeocode.get(1).get("citycode"))) {
                    priceCaculationPrice.setOutCityFlag(0);
                    priceCaculationPrice.setCityFee(outCityFee.longValue());
                } else {
                    priceCaculationPrice.setOutCityFlag(1);
                    /** 计算出城费 总里程 * 出城费单价 */
                    outCityFee = distance.multiply(outCityPerFee).multiply(new BigDecimal(100));

                    priceCaculationPrice.setCityFee(outCityFee.longValue());
                }

                /** 计算夜间行车费，计算逻辑：以订单开始时间为依据，若开始时间在时间区间内则收取，否则不收 */
                Date strToDate = priceCaculationPrice.getOrderStartTime();

                /** 如果有夜间服务费，则计算  总里程 * 夜间服务费单价 */
                if (DateUtil.belongCalendar(tPriceCaculationRule.getNightPriceStartTime(), tPriceCaculationRule.getNightPriceEndTime(), strToDate)) {
                    eveFee = distance.multiply(evePerFee).multiply(new BigDecimal(100));
                    priceCaculationPrice.setEveFee(eveFee.longValue());
                }
            }

            /** 调用优惠券查询接口，查询用户相关联优惠券信息 */
            try {
                Long customerId = priceCaculationPrice.getCustomerId();
                if (null != customerId) {
                    Long trigger = startFee.longValue() + minuteFee.longValue() + mileFee.longValue() + travelTotleFee.longValue() + eveFee.longValue() + outCityFee.longValue();
                    List<Coupon> list = couponClient.queryUsableCoupon(
                            customerId, 1, 1,
                            priceCaculationPrice.getCarType().longValue(),
                            priceCaculationPrice.getCityId().longValue(),
                            priceCaculationPrice.getOrderType(),
                            priceCaculationPrice.getCalType().longValue(),
                            priceCaculationPrice.getOrderChannel(),
                            priceCaculationPrice.getUseType(),
                            trigger, priceCaculationPrice.getOrderStartTime().getTime());

                    if (CollectionUtils.isNotEmpty(list)) {
                        Coupon coupon = list.get(0);
                        conponFee = coupon.getMoney();
                        priceCaculationPrice.setCouponId(coupon.getKid());
                        priceCaculationPrice.setCouponFee(conponFee);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            /** 是否套餐0否1是 */
            priceCaculationPrice.setType(0);

            /** 总价汇总（未抹零）计算 总价 = 起步价 + 时长总价 + 公里总价 + 远途总价 + 夜间服务总价 + 出城总价 */
            totalPrice = startFee.longValue() + minuteFee.longValue() + mileFee.longValue() + travelTotleFee.longValue() + eveFee.longValue() + outCityFee.longValue();

            /** 减优惠券之前的总计预估价 分 */
            priceCaculationPrice.setTotalMoney(totalPrice);

            /** 总计预估价，未抹零 */
            totalPrice = totalPrice - conponFee;

            if (totalPrice < 0) {
                totalPrice = 0L;
            }
            priceCaculationPrice.setTotals(totalPrice);

            /** 总价抹零 */
            String sTotalPrice = String.valueOf(totalPrice);

            if (totalPrice > 0 && sTotalPrice.length() >= 2) {
                zero = Long.valueOf(sTotalPrice.substring(sTotalPrice.length() - 2, sTotalPrice.length()));
            } else {
                zero = 0L;
            }

            /** 抹零后总价 */
            totalMoney = totalPrice - zero;

            priceCaculationPrice.setZero(zero);
            priceCaculationPrice.setTotalFee(totalMoney);
        } else {
            throw new BusinessException(SystemVariable.ERROR_RETURN_CODE, "未查询到有效报价基础规则！");
        }

        /** 预估价信息入库 */
        if (priceCaculationPriceMapper.insertSelective(priceCaculationPrice) > 0) {
            return priceCaculationPrice;
        } else {
            throw new BusinessException(SystemVariable.ERROR_RETURN_CODE, "预估价信息入库失败");
        }

    }

    public PriceCaculationPrice getPriceCaculationPriceByOrderId(String orderId) {
        return priceCaculationPriceMapper.getPriceCaculationPriceByOrderId(orderId);
    }

    public void test(int qos, String payload) throws MqttException {
        mqttService.init();
        mqttService.doPublish(qos, true, payload, mqttService);

    }

    public void testCus() {
        //订阅消息
        int[] qos = {1};
        String[] topic1 = {"mileageRecordUpload/#"};
        mqttClient.getMqttMessage(qos, topic1);
//        System.out.println(gaodeApi.getGaodeRestapi("112.8822040000,28.2315680000,","112.9359300000,27.829250000",5));

    }

}
